package com.pucong.gitee.database.backup.business.unRelational.redis.service;

import com.pucong.gitee.database.backup.business.unRelational.redis.cover.AutoRedisBeanConvert;
import com.pucong.gitee.database.backup.business.unRelational.redis.mapper.AutoRedisMapper;
import com.pucong.gitee.database.backup.business.unRelational.redis.util.ClusterUtil;
import com.pucong.gitee.database.backup.business.unRelational.redis.util.JschUtil;
import com.pucong.gitee.database.backup.business.unRelational.redis.util.RedisDataUtil;
import com.pucong.gitee.database.backup.business.unRelational.redis.util.RedisTelnetUtil;
import com.pucong.gitee.database.backup.common.entity.redis.AutoRedisInfo;
import com.pucong.gitee.database.backup.common.entity.redis.ConfigBean;
import com.pucong.gitee.database.backup.common.entity.redis.RedisConnect;
import com.pucong.gitee.database.backup.common.entity.redis.vo.AutoRedisInfoVo;
import com.pucong.gitee.database.backup.common.entity.sys.UserJwt;
import com.pucong.gitee.database.backup.common.selfenum.CommonBoolenEnum;
import com.pucong.gitee.database.backup.configuration.exception.BusinessException;
import com.pucong.gitee.database.backup.utils.RedisUtil;
import com.pucong.gitee.database.backup.utils.UUID;
import com.pucong.gitee.database.backup.utils.UserRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * redis service接口
 *
 * @author PC
 */
@Service
@Slf4j
public class AutoRedisServiceImpl implements AutoRedisService {

    @Autowired
    private AutoRedisMapper autoRedisMapper;

    @Autowired
    private AutoRedisConnectService autoRedisConnectService;

    @Autowired
    private AutoRedisBeanConvert autoRedisBeanConvert;

    @Override
    public AutoRedisInfoVo getBaseInfoById(String id) {
        AutoRedisInfo autoRedisInfo = autoRedisMapper.selectById(id);
        return autoRedisBeanConvert.do2vo(autoRedisInfo);
    }

    @Override
    public int saveBaseInfo(RedisConnect dto) {
        AutoRedisInfo autoRedisInfo = autoRedisBeanConvert.dto2do(dto);
        if (StringUtils.isBlank(dto.getUuid())) {
            UserJwt loginUser = UserRequest.getLoginUser();
            autoRedisInfo.setUuid(UUID.uuid());
            autoRedisInfo.setCreateBy(loginUser.getUuid());
            autoRedisInfo.setCreateTime(new Date());
            autoRedisMapper.insert(autoRedisInfo);
        } else {
            autoRedisMapper.updateById(autoRedisInfo);
        }
        return 1;
    }

    @Override
    public Boolean connectTest(RedisConnect connect) {
        try {
            String host = connect.getRHost();
            int port = connect.getRPort();
            if (CommonBoolenEnum.是 == connect.getConnectType()) {
                JschUtil.openSSH(connect);
                port = 55555;
                if (host.equals(connect.getSHost())) {
                    host = "127.0.0.1";
                }
            }
            Jedis jedis = new Jedis(host, port, 3000);
            jedis.connect();
            if (!jedis.isConnected()) {
                throw new BusinessException("连接不可用");
            }
            if (StringUtils.isNotBlank(connect.getRPass())) {
                jedis.auth(connect.getRPass());
            }
            jedis.ping();
            jedis.disconnect();
            jedis.close();
            JschUtil.closeSSH();
            return true;
        } catch (Exception e) {
            log.error("连接测试失败", e);
            String msg = e.getMessage();
            if (msg.contains("Auth fail")) {
                throw new BusinessException("SSH认证失败");
            }
            if (msg.contains("UnknownHostKey")) {
                throw new BusinessException("未知的主机");
            }
            if (msg.contains("connect failed")) {
                throw new BusinessException("网络不可达");
            }
            if (msg.contains("invalid password")) {
                throw new BusinessException("密码不正确");
            }
            if (msg.contains("connect timed out")) {
                throw new BusinessException("请求服务超时");
            }
            if (msg.contains("Connection refused")) {
                throw new BusinessException("服务拒绝连接");
            }
            if (msg.contains("Authentication required")) {
                throw new BusinessException("密码不能为空");
            }
            if (msg.contains("socket is not established")) {
                throw new BusinessException("打开SSH连接超时");
            }
            throw new BusinessException("服务不可用");
        }
    }

    @Override
    public List<ConfigBean> getConfInfo(String id) {
        Jedis jedis = autoRedisConnectService.getJedis(id);
        List<ConfigBean> redisConfig = RedisUtil.getRedisConfig(jedis);
        jedis.close();
        return redisConfig;
    }

    @Override
    public void setConfInfo(String id, List<ConfigBean> configBeanList) {
        Jedis jedis = autoRedisConnectService.getJedis(id);
        Map<String, String> confMap = new HashMap<>();
        for (ConfigBean configBean : configBeanList) {
            confMap.put(configBean.getKey(), configBean.getValue());
        }
        RedisUtil.setRedisConfig(jedis, confMap);
        jedis.close();
    }

    @Override
    public void disconConnect(String id) {
        UserJwt loginUser = UserRequest.getLoginUser();
        AutoRedisInfo autoRedisInfo = autoRedisMapper.selectById(id);
        if (autoRedisInfo.getIsHa() == CommonBoolenEnum.否) {
            Jedis jedis = autoRedisConnectService.getJedis(id);
            jedis.close();
            autoRedisConnectService.clearConfig(id);
        } else {
            closeCulter(loginUser.getUuid(), id);
            autoRedisConnectService.clearConfig(id);
        }
    }

    public void closeCulter(String userId, String redisId) {
        RedisConnect connect = autoRedisConnectService.getRedisConnect(redisId);
        JedisCluster cluster = ClusterUtil.openCulter(connect);
        try {
            if (cluster != null) {
                cluster.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Boolean isopenConnect(String id) {
        UserJwt loginUser = UserRequest.getLoginUser();
        RedisConnect connect = autoRedisConnectService.getRedisConnect(id);
        if (null != connect) {
            if (!StringUtils.isEmpty(id) && !connect.getUuid().equals(id)) {
                return false;
            }
            if (connect.getIsHa() == CommonBoolenEnum.否) {
                Jedis jedis = autoRedisConnectService.getJedis(id);
                jedis.close();
                return true;
            } else {
                Object jedisCluster = autoRedisConnectService.getJedisCluster(id);
                if (null != jedisCluster) {
                    return true;
                } else {
                    return false;
                }
            }
        } else {
            return false;
        }
    }

    @Override
    public String cmdwinConnect(String id, String cmd) {
        RedisConnect connect = autoRedisConnectService.getRedisConnect(id);
        if (null != connect) {
            return RedisTelnetUtil.sendCommand(connect, cmd);
        } else {
            disconConnect(id);
            return "";
        }

    }

    @Override
    public void deleteSourceInfo(String id) {
        autoRedisMapper.deleteById(id);
    }
}
